package com.xxg.renrenlogin.service;

import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.xxg.renrenlogin.cache.RrenrenShopUserCache;
import com.xxg.renrenlogin.dao.RenrenShopShop;
import com.xxg.renrenlogin.dao.RenrenShopShopDao;
import com.xxg.renrenlogin.dao.RenrenShopUser;
import com.xxg.renrenlogin.dao.RenrenShopUserDao;
import com.xxg.renrenlogin.domain.query.CodeLoginQuery;
import com.xxg.renrenlogin.domain.query.CodeVerifyQuery;
import com.xxg.renrenlogin.domain.query.TokenLoginQuery;
import com.xxg.renrenlogin.domain.result.BaseResult;
import com.xxg.renrenlogin.domain.result.LoginReturnCodeEnum;
import com.xxg.renrenlogin.domain.result.PasswordLoginResult;
import com.xxg.renrenlogin.exception.ErrorMessage;
import com.xxg.renrenlogin.service.common.TokenCommon;
import com.xxg.renrenlogin.util.JwtUtils;
import com.xxg.renrenlogin.util.RestServiceUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class LoginServiceImpl implements LoginService {

    private static final Logger logger = LoggerFactory.getLogger(LoginServiceImpl.class);
    private final RrenrenShopUserCache renrenShopUserCache;
    private final TokenCommon tokenCommon;
    private final JiGuangService jiGuangService;
    private final RenrenShopUserDao renrenShopUserDao;
    private final RenrenShopShopDao renrenShopShopDao;


    public LoginServiceImpl(RrenrenShopUserCache renrenShopUserCache, TokenCommon tokenCommon,
                            JiGuangService jiGuangService, RenrenShopUserDao renrenShopUserDao,
                            RenrenShopShopDao renrenShopShopDao) {
        this.renrenShopUserCache = renrenShopUserCache;
        this.tokenCommon = tokenCommon;
        this.jiGuangService = jiGuangService;
        this.renrenShopUserDao = renrenShopUserDao;
        this.renrenShopShopDao = renrenShopShopDao;
    }

    @Override
    public BaseResult tokenLogin(TokenLoginQuery tokenLoginQuery) {
        // token验证
        DecodedJWT decodedToken;
        try {
            decodedToken = JwtUtils.verifyJwtToken(tokenLoginQuery.getToken(), JwtUtils.SECRET);
        } catch (JWTVerificationException e) {
            logger.error(ErrorMessage.VERIFY_TOKEN_ERROR, e);
            return new BaseResult(LoginReturnCodeEnum.FAILURE, ErrorMessage.VERIFY_TOKEN_ERROR, null);
        }
        // 提取帐号和token时间戳和证书类型
        String account = decodedToken.getIssuer();
        String timestamp = decodedToken.getClaim("timestamp").asString();
        // 根据从token中解析进行验证，防止token盗用
        List<String> values = renrenShopUserCache.queryCacheByAccount(account);
        if (values == null) {
            logger.error(ErrorMessage.PHONE_ACCOUNT_NOT_EXIST + ":账号不存在"
                    + "\n参数:" + account);
            return new BaseResult(LoginReturnCodeEnum.FAILURE, ErrorMessage.PHONE_ACCOUNT_NOT_EXIST, null);
        }
        // 时间戳是否匹配
        if (!values.get(1).equals(timestamp)) {
            logger.error(ErrorMessage.INVALID_TOKEN_ERROR + ":token令牌时间戳不匹配"
                    + "\n参数:" + timestamp + "\n时间戳:" + values.get(1));
            return new BaseResult(LoginReturnCodeEnum.FAILURE, ErrorMessage.INVALID_TOKEN_ERROR, null);
        }
        return tokenCommon.createNewToken(account, values.get(0), values.get(2), values.get(3));
    }

    @Override
    public BaseResult getCode(String mobile) {
        return jiGuangService.getCode(mobile);
    }

    @Override
    public BaseResult codeLogin(CodeLoginQuery codeLoginQuery) {
        CodeVerifyQuery codeVerifyQuery = new CodeVerifyQuery();
        codeVerifyQuery.setCode(codeLoginQuery.getCode());
        codeVerifyQuery.setMsgId(codeLoginQuery.getMsgId());
        // 查询验证码是否正确
        boolean valid = jiGuangService.codeVerify(codeVerifyQuery);
        if (valid) {
            // 查询账户信息
            List<String> values = renrenShopUserCache.queryCacheByAccount(codeLoginQuery.getMobile());
            if (values == null) {
                logger.error(ErrorMessage.PHONE_ACCOUNT_NOT_EXIST + ":账号不存在"
                        + "\n参数:" + codeLoginQuery.getMobile());
                return new BaseResult(LoginReturnCodeEnum.FAILURE, ErrorMessage.PHONE_ACCOUNT_NOT_EXIST, null);
            }
            return tokenCommon.createNewToken(codeLoginQuery.getMobile(), values.get(0), values.get(2), values.get(3));
        } else {
            return new BaseResult(LoginReturnCodeEnum.CODE_CHECK_FAILURE, ErrorMessage.INVALID_CODE, null);
        }
    }

    @Override
    public BaseResult passwordLogin(String username, String password) {
        RenrenShopUser user = renrenShopUserDao.selectByAccount(username);
        if (user == null) {
            return new BaseResult(LoginReturnCodeEnum.FAILURE, ErrorMessage.USER_OR_PASSWORD_ERROR, null);
        }
        RenrenShopShop shop = renrenShopShopDao.selectByUserId(user.getId());
        String shopId = "-1";
        if (shop != null) {
            shopId = shop.getId().toString();
        }
        // 验证密码
        String p = password + user.getSalt();
        boolean b = new BCryptPasswordEncoder(BCryptPasswordEncoder.BCryptVersion.$2Y, 10)
                .matches(p, user.getPassword());
        if (b) {
            return tokenCommon.createNewToken(username, user.getGroupId().toString(), user.getId().toString(), shopId);
        } else {
            return new BaseResult(LoginReturnCodeEnum.FAILURE, ErrorMessage.USER_OR_PASSWORD_ERROR, null);
        }
    }
}
